#include <EEPROM.h>

#if EEPROM_EN

static uint8_t config_flg = 0;
static uint8_t eeprom_buffer[EEPROM_SIZE] = {0};

void eeprom_set_clk(uint32_t sys_clk)
{
    sys_clk = (sys_clk / 100000 + 5) / 10;
#ifdef STC8A8K64S4A12_8F_TYPE
    IAP_CONTR &= 0xf0;
    IAP_CONTR |= (uint8_t)sys_clk;
#else
    IAP_TPS = (uint8_t)sys_clk;
#endif
    config_flg = 1;
}

static void set_add(uint16_t addr)
{
    IAP_ADDRL = addr;      //设置IAP低地址
    IAP_ADDRH = addr >> 8; //设置IAP高地址
}

static uint8_t chek_result()
{
    if (IAP_CONTR & 0x10)
    {
        IAP_CONTR &= 0xef;
        return 0;
    }
    else
        return 1;
}

static void cmd_trig()
{
    IAP_TRIG = 0x5a; //写触发命令(0x5a)
    IAP_TRIG = 0xa5; //写触发命令(0xa5)
    _nop_();
}

static uint8_t iap_read(uint16_t addr)
{
    IAP_CMD = 1; //设置IAP读命令
    set_add(addr);
    cmd_trig();
    return (uint8_t)IAP_DATA;
}

static void iap_write(uint16_t addr, uint8_t dat)
{
    IAP_CMD = 2; //设置IAP写命令
    set_add(addr);
    IAP_DATA = dat; //写IAP数据
    cmd_trig();
}

static void iap_erase(uint16_t addr)
{
    IAP_CMD = 3; //设置IAP擦除命令
    set_add(addr);
    cmd_trig();
}

uint8_t eeprom_begin()
{
    uint16_t i;
    if (config_flg == 1)
    {
        config_flg = 2;
        IAP_CONTR &= 0xef;
        IAP_CONTR |= 0x80; //使能IAP
        for (i = 0; i < EEPROM_SIZE; i++)
        {
            eeprom_buffer[i] = iap_read(i);
            if (chek_result() == 0)
            {
                eeprom_end();
                return 0;
            }
        }
        return 1;
    }
    else
        return 0;
}

void eeprom_end()
{
    IAP_CONTR &= 0x7f; //关闭IAP功能
    IAP_CMD = 0;       //清除命令寄存器
    IAP_TRIG = 0;      //清除触发寄存器
    IAP_ADDRH = 0x80;  //将地址设置到非IAP区域
    IAP_ADDRL = 0;
    if (config_flg == 2)
        config_flg = 1;
}

void eeprom_write(uint16_t addr, uint8_t dat)
{
    if (config_flg != 2)
        return;
    if (addr >= EEPROM_SIZE)
        return;
    eeprom_buffer[addr] = dat;
}

uint8_t eeprom_read(uint16_t addr)
{
    if (config_flg != 2)
        return 0;
    if (addr >= EEPROM_SIZE)
        return 0;
    return eeprom_buffer[addr];
}

uint8_t eeprom_commit()
{
    uint16_t i;
    if (config_flg != 2)
        return 0;
    iap_erase(0);
    if (chek_result() == 0)
        return 0;
    for (i = 0; i < EEPROM_SIZE; i++)
    {
        iap_write(i, eeprom_buffer[i]);
        if (chek_result() == 0)
        {
            return 0;
        }
    }
    return 1;
}

uint8_t eeprom_write_bytes(uint16_t addr, uint8_t *dat, uint16_t len)
{
    if (addr >= EEPROM_SIZE)
        return 0;
    if ((addr + len) >= EEPROM_SIZE)
    {
        len = EEPROM_SIZE - addr;
    }
    if (eeprom_begin())
    {
        memcpy(&eeprom_buffer[addr],dat,len);
        if (eeprom_commit())
        {
            eeprom_end();
            return 1;
        }
        else
        {
            eeprom_end();
            return 0;
        }
    }
    else
        return 0;
}
uint8_t eeprom_read_bytes(uint16_t addr, uint8_t *buffer, uint16_t len)
{
    if (addr >= EEPROM_SIZE)
        return 0;
    if ((addr + len) >= EEPROM_SIZE)
    {
        len = EEPROM_SIZE - addr;
    }
    if (eeprom_begin())
    {
        memcpy(buffer,&eeprom_buffer[addr],len);
        eeprom_end();
        return 1;
    }
    else
        return 0;
}

#endif
